<template>
    <div>
        <!-- v-model="input.val"  等同于  :value="input.val" @input="updateValue"-->
        <input
        v-if="tag==='input'"
        class="form-control"
        :class="{'is-invalid':input.error}"
        v-model="inputRef.val"
        @blur='ValidateInput'
        v-bind="$attrs"/>
        <textarea 
        v-else
        class="form-control"
        :class="{'is-invalid':input.error}"
        v-model="inputRef.val"
        @blur='ValidateInput'
        v-bind="$attrs"
        />
        <span v-if='input.error' class="invalid-feedback">{{input.message}}</span>
    
    </div>
</template>
<script lang="ts">
import {defineComponent, onMounted, PropType, reactive,watch,computed} from 'vue'
import bus from '../bus'
const emailReg = /^[a-zA-Z0-9.!#$%&’*+/=?^_`{|}~-]+@[a-zA-Z0-9-]+(?:\.[a-zA-Z0-9-]+)*$/
interface RuleProp{
    type:'required'|'email'|'custom',
    message:string,
    validator?:()=>boolean   //自定义校验规则 validator
}
export type RulesProp=RuleProp[]
export type TagType='input'|'textarea'

export default defineComponent({
    name:'ValidateInput',
    props:{
        rules:Array as PropType<RulesProp>,
        modelValue:String,
        tag:{
            //String：注意了 这个时候也用  PropType
            type:String as PropType<TagType>,
            default:'input'
        }
    },
    // attrs  设置div外壳不直接继承传过来的placeholder,在对应的元素上加v-bind="$attrs"就可以继承
    inheritAttrs:false,
    setup(props,context){
        console.log(context.attrs)
        const input=reactive({
            val:props.modelValue || '',
            error:false,
            message:''
        })
         const inputRef = reactive({
            val: computed({
                get: () => props.modelValue || '',
                set: val => {
                context.emit('update:modelValue', val)
                }
            }),
            error: false,
            message: ''
        })
        watch(()=>props.modelValue,(newValue)=>{
            inputRef.val=newValue || ''
        })
        const updateValue=(e:KeyboardEvent)=>{
            const targetValue=(e.target as HTMLInputElement).value
            input.val=targetValue
            //更新数据 v-model
            context.emit('update:modelValue',targetValue)
        }
        const ValidateInput=()=>{
            if(props.rules){
                const allPassed=props.rules.every(rule=>{
                    let passed=true
                    input.message=rule.message
                    switch(rule.type){
                        case 'required': passed=(input.val.trim()!=='')
                        break
                        case 'email':passed=emailReg.test(input.val)
                        break
                        case 'custom':passed=rule.validator ? rule.validator():true
                        break
                        default:
                        break
                    }
                    return passed
                })
                input.error=!allPassed
                return allPassed
            }
            return true
        }
        onMounted(()=>{
            bus.$emit('form-item-created',ValidateInput)
        })
        return {
            input,
            ValidateInput,
            updateValue
        }
    }

})
</script>
<style scoped>
.is-invalid{
    color: red;
}
</style>